package top.chukongxiang.project.base.controller.sys;

import lombok.AllArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import top.chukongxiang.project.base.model.entity.sys.Menu;
import top.chukongxiang.project.base.model.entity.sys.RoleMenu;
import top.chukongxiang.project.base.model.response.R;
import top.chukongxiang.project.base.model.response.RCode;
import top.chukongxiang.project.base.model.vo.sys.MenuTreeVo;
import top.chukongxiang.project.base.service.sys.MenuService;
import top.chukongxiang.project.base.service.sys.RoleMenuService;
import top.chukongxiang.project.base.utils.ArrayUtils;
import top.chukongxiang.project.base.utils.TreeUtils;

import java.util.List;
import java.util.Objects;

/**
 * 菜单相关
 * @author 楚孔响
 * @version 1.0
 * @date 2022/2/18 15:26
 */
@RestController
@RequestMapping("menu")
@AllArgsConstructor
public class MenuController {

    private final MenuService menuService;
    private final RoleMenuService roleMenuService;

    /**
     * 根据父级菜单id获取子级菜单列表
     * @param parentId 父级菜单id，null为顶级
     * @return 子级菜单列表
     */
    @GetMapping("list-by-parent")
    public R<List<Menu>> list(@RequestParam(required = false) Long parentId) {
        List<Menu> menus = menuService.listByParentId(parentId);
        return R.ok(menus);
    }

    /**
     * 保存或更新菜单
     * @param menu 菜单信息，id为null时新增，反之修改
     * @return 修改后的信息
     */
    @PutMapping
    public R<Menu> savOrUpdate(@RequestBody @Validated Menu menu) {
        boolean success = menuService.saveOrUpdate(menu);
        return success ? R.ok(menu) : R.failed(RCode.REMOVED);
    }

    /**
     * 根据菜单id删除菜单
     * @param menuId 菜单id
     * @return 被删除的菜单的id
     */
    @DeleteMapping("{menuId}")
    public R<Long> removeById(@PathVariable Long menuId) {
        // 检查是否绑定了角色
        if (roleMenuService.checkMenuIsBandRole(menuId)) {
            return R.failed("该菜单绑定了角色，请先删除绑定关系!");
        }
        boolean success = menuService.removeById(menuId);
        return success ? R.ok(menuId) : R.failed(RCode.REMOVED);
    }

    /**
     * 获取树形菜单列表(全部)
     * @return 树形菜单
     */
    @GetMapping("tree-all")
    public R<List<MenuTreeVo>> treeAllMenu() {
        List<Menu> menus = menuService.list();
        List<MenuTreeVo> menuTree = TreeUtils.parseTree(menus,
                MenuTreeVo.class,
                MenuTreeVo::getId,
                MenuTreeVo::getParentId,
                MenuTreeVo::getChildren,
                MenuTreeVo::setChildren,
                Objects::deepEquals,
                null);
        return R.ok(menuTree);
    }

    /**
     * 获取一个role已经绑定了的菜单
     * @param roleId 角色id
     * @return
     */
    @GetMapping("role-menu/{roleId}")
    public R<List<String>> listMenuIdsByRoleId(@PathVariable Long roleId) {
        List<Long> menuIds = roleMenuService.listMenuIdByRoleId(roleId);
        return R.ok(ArrayUtils.map(menuIds, menuId -> menuId+""));
    }

    /**
     * 绑定一个role的菜单
     * @param roleId 角色id
     * @param menuIds 菜单id列表
     * @return
     */
    @PostMapping("save-role-menu/{roleId}")
    public R<?> saveRoleMenu(@PathVariable Long roleId, @RequestBody List<Long> menuIds) {
        roleMenuService.removeByRoleId(roleId);
        List<RoleMenu> roleMenus = ArrayUtils.map(menuIds, menuId -> new RoleMenu(null, roleId, menuId));
        boolean success = roleMenuService.saveBatch(roleMenus);
        return success ? R.ok() : R.failed();
    }



}
